import json
import pathlib
from copy import deepcopy

from flask import Flask, request, jsonify, make_response, send_from_directory
from service import projectService, processService, emService, emServiceProsumer
from utils.common import *
from utils.jsonData import *

app = Flask(__name__)

das_path = pathlib.Path(".").absolute()
project_dir_path = das_path / "project"


@app.route("/project", methods=["GET"])
def query_project():
    _res = projectService.query_project()
    return _res


@app.route("/project/<int:project_id>", methods=["GET"])
def query_project_by_id(project_id):
    _res = projectService.query_project_by_id(project_id)
    return _res


@app.route("/process/<int:process_id>", methods=["GET"])
def query_process_by_id(process_id):
    _res = processService.query_process_by_id(process_id)
    return _res


@app.route("/process", methods=["GET"])
def query_process():
    _res = processService.query_process()
    return _res


@app.route("/em", methods=["GET"])
def query_running_project():
    _res = emService.query_running_project()
    return _res


@app.route("/em/<string:ip>", methods=["GET"])
def get_consumer(ip):
    _res = emService.get_consumer(ip)
    return jsonify(_res)


@app.route("/em/run", methods=["POST"])
def start_local_process():
    _res = emServiceProsumer.start_local_process(request.json)
    return _res


@app.route("/em/stop", methods=["POST"])
def stop_local_process():
    _res = emService.stop_local_process(request.json)
    return _res


@app.route("/project/<int:project_id>/resource", methods=["GET"])
def get_project_file(project_id):
    judge, _res = projectService.query_project_by_id(project_id)
    if not judge:
        return _res
    _res = json.loads(_res)
    project_name = _res["data"][0]["name"]
    return send_file_from_local(project_id, project_name)


@app.route("/project/<int:project_id>/config", methods=["GET"])
def get_project_config(project_id):
    _res = projectService.query_project_config_by_id(project_id)
    return _res


@app.route("/project/<int:project_id>", methods=["PUT"])
def put_project_by_id(project_id):
    file = request.files.get("file")
    if file is None:
        return JsonData().error("1006", "未上传文件")
    _res = projectService.update_project_by_id(project_id, file, request.remote_addr)
    return _res


@app.route("/project/<int:project_id>/config", methods=["PUT"])
def put_project_config(project_id):
    if not request.json:
        return JsonData().error("1008", "没有获得json数据")
    _res = projectService.update_project_config(project_id, request.json)
    return _res


@app.route("/process/<int:process_id>", methods=["PUT"])
def put_process(process_id):
    if not request.json:
        return JsonData().error("1008", "没有获得json数据")
    _res = processService.update_process(process_id, request.json)
    return _res


@app.route("/project/<int:project_id>", methods=["DELETE"])
def delete_project(project_id):
    _res = projectService.delete_project_by_id(project_id)
    return _res


@app.route("/process/<int:process_id>", methods=["DELETE"])
def delete_process(process_id):
    _res = processService.delete_process_by_id(process_id)
    return _res


@app.route("/project", methods=["POST"])
def upload_project():
    file = request.files.get("file")
    if file is None:
        return JsonData().error("1006", "未上传文件")
    _res = check_and_extract_project(file)
    return _res


@app.route("/process", methods=["POST"])
def add_process():
    process_dict = request.json
    _res = processService.addProcess(process_dict)
    return _res


def send_file_from_local(project_id, project_name):
    """发送本地文件至客户端"""
    project_file_path = das_path / "project" / f"{project_name}{project_id}"
    judge, _res = project_to_package(project_file_path, project_id)
    if not judge:
        return _res
    project_file_path = pathlib.Path(_res)
    start_time = time.time()
    while time.time()-start_time < 2:
        if pathlib.Path(project_file_path).is_file():
            break
    try:
        app.config[f"DOWNLOAD_FOLDER"] = str(project_dir_path)
        response = make_response(
            send_from_directory(app.config[f"DOWNLOAD_FOLDER"], project_file_path.name, as_attachment=True)
        )
        return response
    except Exception as e:
        return JsonData().error("1007", f"{project_file_path.name}下载失败.{e}, ")


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=11113, debug=True)
